package org.hades.corelib.base.vm

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.*
import org.hades.corelib.base.data.UIState

open class CoreViewModel : ViewModel() {

    var uiChannel: Channel<UIState> = Channel()
    val uiStateFlow = uiChannel.receiveAsFlow()

    open fun onStartLoad() {
        viewModelScope.launch {
            uiChannel.send(
                UIState.OnLoading
            )
        }
    }

    open fun onComplete() {
        viewModelScope.launch {
            uiChannel.send(
                UIState.OnComplete
            )
        }
    }

    open fun handleExecption(e: Exception) {
        postErrorUI(e)
    }

    private fun postErrorUI(exception: Exception) {
        viewModelScope.launch {
            uiChannel.send(
                UIState.OnExecption(exception)
            )
        }
    }


    /**
     *  Use with LiveData or StateFlow drop first count
     *  适合 统一处理异常，数据不用ResultData包装的情况
     *  Must used in CoreViewModel
     */
    fun <T> Flow<T>.composeNomal(
    ): Flow<T> {
        return this.onStart {
            onStartLoad()
            delay(300) }
            .catch { e ->
                run {
                    handleExecption(e as Exception)
                }
            }
            .onCompletion { onComplete() }
    }

    /**
     *  Use with LiveData or StateFlow
     * 适合 统一处理异常，数据用ResultData包装的情况
     */
    fun <T> Flow<T>.composeState(
        block: suspend (e:Exception)->Unit
    ): Flow<T> {
        return this.onStart {
            delay(300) }
            .catch { e ->
                block.invoke(e as Exception)
            }
            .onCompletion { onComplete() }
    }


}